/*
 * Classe ListTwo
 *                          - Obtem os dados da lista 2 da base de dados (SQLite3 + ADO.NET) 
 * 							- Guarda esses dados numa Lista (C# Collections)
 * 							- Ordena os dados
 * 							- Escreve os resultados na consola e no ficheiro de texto respectivo
 *							- Tem como atributo o estabelecimento sobre o qual serão obtidos os dados
 *
 *@Author: Fábio Miguel Vitória Carreto - 5618 - Engenharia Informática - Diurno
 *@Version: 03/07/2011
 * 
 * 
 * */


using System;
using System.Collections.Generic;
using System.Data;
using Mono.Data.SqliteClient;
using System.IO;

public class ListTwo
{
	public string estabelecimento;

	
	public ListTwo (string estabelecimento)
	{
		this.estabelecimento = estabelecimento;
		
		//Para cada ano executa os seguintes métodos
		for(int ano = 0 ; ano < 10 ; ano++)
		{
			
			List<StructFinalListaDois> listTwo = this.getData(ano);
			List<StructFinalListaDois> listOrdenada = this.mostraListaOrdenada(listTwo);
			this.showResultsConsole(listOrdenada, ano);
			this.showResultsFile(listOrdenada, ano);	

			
		}
	}
	
	//Ordena os dados por ordem alfabética do nome de docente
	public List<StructFinalListaDois> mostraListaOrdenada(List<StructFinalListaDois> list)
	{
		list.Sort(delegate(StructFinalListaDois s1, StructFinalListaDois s2) 
		          { return s1.nome_docente.CompareTo(s2.nome_docente); });
		
		return list;
	}
	
	//Mostra resultados na consola
	public void showResultsConsole(List<StructFinalListaDois> list, int ano)
	{
		
		Console.WriteLine("ANO DE 200" + ano + "\nDOCENTES EM NOVOS ESTABELECIMENTOS EM RELAÇÃO AO ANO ANTERIOR:");
		Console.WriteLine("\nResultados (Ordenados por Ordem Alfabética do Nome de Docente em Cada Ano):\n");
		list.ForEach(delegate(StructFinalListaDois s) 
		{ 
			Console.WriteLine(String.Format("Docente: {0} \nNovo Estabelecimento: {1}", s.nome_docente, s.novo_estabelecimento)); 
		});
		
	}
	
	//Mostra resultados no ficheiro respectivo
	public void showResultsFile(List<StructFinalListaDois> list, int ano)
	{
		
		string file = "Listas/listTwo.txt";
		
		//Quando o ano é 0, é definido o cabeçalho da lista
		if(ano == 0)
		{
			
			TextWriter tw = new StreamWriter(file);
			tw.WriteLine(DateTime.Now);
			tw.WriteLine("Sistema Operativo: " + Environment.OSVersion.ToString());
			tw.WriteLine("");
			tw.WriteLine("Lista 2 - Docentes que mudaram de estabelecimento em cada ano");
			tw.WriteLine(Environment.NewLine + "(Resultados ordenados por ordem alfabética do nome do docente em cada ano)");
			tw.Close();
			
		}
		
		
		
		list.ForEach(delegate(StructFinalListaDois s) 
		{
			File.AppendAllText(file, String.Format("Ano = 200{0}, Docente = {1}, Novo Estabelecimento = {2}" + 
			                                       Environment.NewLine, ano, s.nome_docente, s.novo_estabelecimento));
		});
		
		File.AppendAllText(file, Environment.NewLine + Environment.NewLine);
		
		Console.WriteLine("\nOs resultados da lista 2 foram também guardados em ficheiro de texto.");
		Console.WriteLine("Localização: " + file);
		
	}
	
	//Obtém os dados da lista e retorna-os numa lista de objectos
	public List<StructFinalListaDois> getData(int ano)
	{
		string connectionString = "URI=file:rebides.db,version=3";
		IDbConnection dbcon;
		dbcon = (IDbConnection) new SqliteConnection(connectionString);
		dbcon.Open();
		IDbCommand dbcmd = dbcon.CreateCommand();
		
		List<StructFinalListaDois> list = new List<StructFinalListaDois>();
		
		//Quando o ano é 2000 não existem resultados anteriores para comparação,
		//logo a lista será vazia
		if(ano == 0)
		{
			list.Add(new StructFinalListaDois(ano, "", ""));
		}
		else
		{
			
			//Verifica primeiro qual os códigos de estabelecimento no ano anterior
			//e actual (ano do ciclo)
			int cod_estabAnt = this.findEstab(ano - 1, this.estabelecimento, dbcon);
			int cod_estabAct = this.findEstab(ano, this.estabelecimento, dbcon);
			
			//Obtem uma lista com os docentes do ano anterior e outra com os do ano actual 
			//(para o estabelecimento pretendido)
			List<StructListTwo> docAnt = this.findDoc(ano - 1, cod_estabAnt, dbcon);
			List<StructListTwo> docAct = this.findDoc(ano, cod_estabAct, dbcon);
			
			//Percorre a lista com os docentes do ano anterior
			foreach(StructListTwo docPrev in docAnt)
			{
				
				//Verifica se no ano actual existe o mesmo docente (objecto) que existia no ano anterior
				StructListTwo teste = docAct.Find((delegate(StructListTwo o) { return o.docente == docPrev.docente; }));
				
				//Caso exista, continua-se, o que quer dizer que ele não mudou de estabelecimento
				if(teste != null)
				{
					continue;
				}
				else
				{
					//Caso não exista vai se verificar se ele está actualmente noutro estabelecimento
					//e obter o nome do mesmo
					string new_estabelecimento = this.fintdDocInEstab(ano, int.Parse(docPrev.docente), dbcon);
						
					if(new_estabelecimento != null)
					{
						//Caso esteja, obtém-se por fim o nome desse docente e define-se o objecto a guardar
						//na lista com as informações obtidas (ano, nome do docente e novo estabelecimento em
						//que se encontra)
						string nome_docente = this.findNomeDocente(0, int.Parse(docPrev.docente), dbcon);
						list.Add(new StructFinalListaDois(ano, nome_docente, new_estabelecimento));	
					
					}
				}	
		
			}	
			
		}
	
	return list;
		
	}
	
	//Método que irá obter o codigo de estabelecimento pelo seu nome e ano
	public int findEstab(int ano, string estabelecimento, IDbConnection dbcon)
	{
		
		IDbCommand dbcmd = dbcon.CreateCommand();
		IDataReader reader = null;

		string sqlEstab = String.Format("SELECT DISTINCT id FROM estabelecimento WHERE " + 
				                           "ano = {0} AND designacao LIKE '{1}'", ano, estabelecimento);
			 
		dbcmd.CommandText = sqlEstab;
		reader = dbcmd.ExecuteReader();
				
		string estabelecimento_id = null;
				
		while(reader.Read()) 
		{
			estabelecimento_id = reader.GetString (0);
		}
		
		return int.Parse(estabelecimento_id);
		
	}
	
	//Método que devolve a lista de docentes num determinado ano para um dado estabelecimento
	public List<StructListTwo> findDoc(int ano, int cod_estab, IDbConnection dbcon)
	{
		
		IDbCommand dbcmd = dbcon.CreateCommand();
		IDataReader reader = null;
		
		List<StructListTwo> docentes = new List<StructListTwo>();
		
		string sqlFinal = String.Format("SELECT docente_id FROM registodocencia WHERE " +
					"ano = {0} AND estabelecimento_id = {1}", ano, cod_estab);
				
		dbcmd.CommandText = sqlFinal;
		reader = dbcmd.ExecuteReader();
				
		while(reader.Read()) 
		{
			string docente = reader.GetString (0);
			docentes.Add(new StructListTwo(docente, ano));
		}
		
		return docentes;
		
	}
	
	//Método que verifica se os docentes estão num estabelecimento
	//Importante para confirmar se os docentes apenas abandoram ou se migraram de estabelecimento
	//Devolve ainda o nome desse estabelecimento
	public string fintdDocInEstab(int ano, int cod_doc, IDbConnection dbcon)
	{
		
		IDbCommand dbcmd = dbcon.CreateCommand();
		IDataReader reader = null;
		
		string sqlFinal = String.Format("SELECT estabelecimento_id FROM registodocencia WHERE " +
					"ano = {0} AND docente_id = {1}", ano, cod_doc);
				
		dbcmd.CommandText = sqlFinal;
		reader = dbcmd.ExecuteReader();
				
		while(reader.Read()) 
		{
			string estab = reader.GetString (0);
			
			if(estab != null)
			{
				//Quando se obtem um id de estabelecimento verifica-se depois qual o seu nome
				string sqlEstab = String.Format("SELECT designacao FROM estabelecimento WHERE " +
					"ano = {0} AND id = {1}", ano, int.Parse(estab));
				
				IDbCommand comand = dbcon.CreateCommand();
				IDataReader finalReader = null;
				
				comand.CommandText = sqlEstab;
				finalReader = comand.ExecuteReader();
				
				while(finalReader.Read())
				{
					return finalReader.GetString (0);
					
				}
				
			}
			else
			{
				continue;
			}
			
		}
		
		return null;
		
		
	}
	
	//Obtém-se o nome de docente com um determinado id
	public string findNomeDocente(int ano, int cod_doc, IDbConnection dbcon)
	{
		
		IDbCommand dbcmd = dbcon.CreateCommand();
		IDataReader reader = null;
		
		string sqlFinal = String.Format("SELECT nome FROM docente " +
				"WHERE id = {0}", cod_doc);
				
		
		dbcmd.CommandText = sqlFinal;
		reader = dbcmd.ExecuteReader();
				
		while(reader.Read()) 
		{
			string docente = reader.GetString (0);
			return docente;	
					
			
		}
		
		return null;
		
	}
	
	
}

//Objecto que servirá controlo à lista
//Tem como atributos docente e ano e servirá para 
//criar as listas de docentes num estabelecimento e ano
//que posteriormente serão comparadas
public class StructListTwo
{
	public string docente;
	public int ano;
	
	public StructListTwo(string docente, int ano)
	{
		
		this.docente = docente;
		this.ano = ano;
		
	}
}

//Objecto que servirá de base à lista final
//Tem como atributos o ano o nome do docente
//e o respectivo novo estabelecimento em que se encontra
public class StructFinalListaDois
{
	public int ano;
	public string nome_docente;
	public string novo_estabelecimento;
	
	public StructFinalListaDois(int ano, string nome_docente, string novo_estabelecimento)
	{
		this.ano = ano;
		this.nome_docente = nome_docente;
		this.novo_estabelecimento = novo_estabelecimento;
	}
}


